package com.lcn.netty;

import com.lcn.netty.initializer.HttpServerInitializer;
import com.lcn.netty.initializer.WebSocketServerInitializer;
import com.lcn.netty.mq.RabbitMQConnectUtils;
import com.lcn.netty.utils.JedisPoolUtils;
import com.lcn.netty.utils.ZookeeperRegister;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import redis.clients.jedis.Jedis;

import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * netty服务的启动类
 */
public class ChatServer {

    public static final int DEFAULT_PORT = 875;

    public static final String EXCHANGE_NAME = "fanout_exchange";

    public static void main(String[] args) throws Exception {
        // 定义主线程池，用于接收客户端的连接，不做任何处理
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        // 定义从线程池，处理主线程交来的任务
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        Integer port = selectPort(DEFAULT_PORT);
        // 注册到zookeeper
        String ip = ZookeeperRegister.getHost();
        ZookeeperRegister.registerNettyServer(ip, port, "server-list");
        // 启动MQ消费者监听
        RabbitMQConnectUtils connectUtils = new RabbitMQConnectUtils();
        String queueName = "netty_queue_" + port;
        connectUtils.listen(EXCHANGE_NAME, queueName);
        try {
            // 构建netty服务器
            ServerBootstrap server = new ServerBootstrap();
            server.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
//                    .childHandler(new HttpServerInitializer());
                    .childHandler(new WebSocketServerInitializer());
            // 启动server，绑定端口号为875，启动方式为同步
            ChannelFuture channelFuture = server.bind(port).sync();
            channelFuture.channel().closeFuture().sync();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }

    /**
     * 获取端口号，每次累加10
     */
    public static Integer selectPort(Integer defaultPort) {
        String key = "netty_port";
        Jedis jedis = JedisPoolUtils.getJedis();
        Map<String, String> portMap = jedis.hgetAll(key);
        // 提取key
        List<Integer> portList = portMap.entrySet().stream()
                .map(Map.Entry::getKey)
                .map(Integer::valueOf)
                .collect(Collectors.toList());
        Integer port = null;
        if (portList == null || portList.size() == 0) {
            // 第一次端口为默认端口
            jedis.hset(key, defaultPort + "", "1");
            port = defaultPort;
        } else {
            // 获取最大的端口
            Optional<Integer> maxPort = portList.stream().max(Integer::compareTo);
            Integer currentPort = maxPort.get();
            port = currentPort + 10; // 每次累加10
            jedis.hset(key, port + "", "1");
        }
        return port;
    }

}
